home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / archiver / unix / zip19p1.zoo / os2 / os2zip.c < prev    next >
C/C++ Source or Header  |  1992-08-26  |  21KB  |  922 lines

  1. /*
  2.  * @(#)dir.c 1.4 87/11/06 Public Domain.
  3.  *
  4.  *  A public domain implementation of BSD directory routines for
  5.  *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  6.  *  August 1897
  7.  *  Ported to OS/2 by Kai Uwe Rommel
  8.  *  December 1989, February 1990
  9.  *  Change for HPFS support, October 1990
  10.  */
  11.  
  12. /* does also contain EA access code for use in ZIP */
  13.  
  14.  
  15. #ifdef __EMX__
  16. #define __32BIT__
  17. #endif
  18.  
  19. #include "zip.h"
  20.  
  21. #include <stdlib.h>
  22. #include <time.h>
  23. #include <ctype.h>
  24.  
  25. #ifdef __WATCOMC__
  26. #include <malloc.h>
  27. unsigned char __near _osmode = OS2_MODE;
  28. #endif
  29.  
  30. #define INCL_NOPM
  31. #define INCL_DOSNLS
  32. #define INCL_DOSERRORS
  33. #include <os2.h>
  34.  
  35. #include "os2zip.h"
  36.  
  37.  
  38. #define EAID     0x0009
  39.  
  40.  
  41. #ifdef __32BIT__
  42. #define DosFindFirst(p1, p2, p3, p4, p5, p6) \
  43.         DosFindFirst(p1, p2, p3, p4, p5, p6, 1)
  44. #else
  45. #define DosQueryCurrentDisk DosQCurDisk
  46. #define DosQueryFSAttach(p1, p2, p3, p4, p5) \
  47.         DosQFSAttach(p1, p2, p3, p4, p5, 0)
  48. #define DosQueryPathInfo(p1, p2, p3, p4) \
  49.         DosQPathInfo(p1, p2, p3, p4, 0)
  50. #define DosSetPathInfo(p1, p2, p3, p4, p5) \
  51.         DosSetPathInfo(p1, p2, p3, p4, p5, 0)
  52. #define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \
  53.         DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)
  54. #define DosFindFirst(p1, p2, p3, p4, p5, p6) \
  55.         DosFindFirst(p1, p2, p3, p4, p5, p6, 0)
  56. #define DosMapCase DosCaseMap
  57. #endif
  58.  
  59.  
  60. #ifndef UTIL
  61.  
  62. extern int noisy;
  63.  
  64. #ifndef S_IFMT
  65. #define S_IFMT 0xF000
  66. #endif
  67.  
  68. static int attributes = A_DIR | A_HIDDEN | A_SYSTEM;
  69.  
  70. static char *getdirent(char *);
  71. static void free_dircontents(struct _dircontents *);
  72.  
  73. #ifdef __32BIT__
  74. static HDIR hdir;
  75. static ULONG count;
  76. static FILEFINDBUF3 find;
  77. #else
  78. static HDIR hdir;
  79. static USHORT count;
  80. static FILEFINDBUF find;
  81. #endif
  82.  
  83.  
  84. DIR *opendir(char *name)
  85. {
  86.   struct stat statb;
  87.   DIR *dirp;
  88.   char c;
  89.   char *s;
  90.   struct _dircontents *dp;
  91.   char nbuf[MAXPATHLEN + 1];
  92.   int len;
  93.  
  94.   strcpy(nbuf, name);
  95.   len = strlen (nbuf);
  96.   s = nbuf + len;
  97.  
  98.   if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&
  99.        (strlen(nbuf) > 1) )
  100.   {
  101.     nbuf[strlen(nbuf) - 1] = 0;
  102.  
  103.     if ( nbuf[strlen(nbuf) - 1] == ':' )
  104.       strcat(nbuf, "\\.");
  105.   }
  106.   else
  107.     if ( nbuf[strlen(nbuf) - 1] == ':' )
  108.       strcat(nbuf, ".");
  109.  
  110.   if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
  111.     return NULL;
  112.  
  113.   if ( (dirp = malloc(sizeof(DIR))) == NULL )
  114.     return NULL;
  115.  
  116.   if ( nbuf[strlen(nbuf) - 1] == '.' )
  117.     strcpy(nbuf + strlen(nbuf) - 1, "*.*");
  118.   else
  119.     if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&
  120.          (strlen(nbuf) == 1) )
  121.       strcat(nbuf, "*.*");
  122.     else
  123.       strcat(nbuf, "\\*.*");
  124.  
  125.   dirp -> dd_loc = 0;
  126.   dirp -> dd_contents = dirp -> dd_cp = NULL;
  127.  
  128.   if ((s = getdirent(nbuf)) == NULL)
  129.     return dirp;
  130.  
  131.   do
  132.   {
  133.     if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
  134.         ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL)      )
  135.     {
  136.       if (dp)
  137.         free(dp);
  138.       free_dircontents(dirp -> dd_contents);
  139.  
  140.       return NULL;
  141.     }
  142.  
  143.     if (dirp -> dd_contents)
  144.     {
  145.       dirp -> dd_cp -> _d_next = dp;
  146.       dirp -> dd_cp = dirp -> dd_cp -> _d_next;
  147.     }
  148.     else
  149.       dirp -> dd_contents = dirp -> dd_cp = dp;
  150.  
  151.     strcpy(dp -> _d_entry, s);
  152.     dp -> _d_next = NULL;
  153.  
  154.     dp -> _d_size = find.cbFile;
  155.     dp -> _d_mode = find.attrFile;
  156.     dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);
  157.     dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);
  158.   }
  159.   while ((s = getdirent(NULL)) != NULL);
  160.  
  161.   dirp -> dd_cp = dirp -> dd_contents;
  162.  
  163.   return dirp;
  164. }
  165.  
  166.  
  167. void closedir(DIR * dirp)
  168. {
  169.   free_dircontents(dirp -> dd_contents);
  170.   free(dirp);
  171. }
  172.  
  173.  
  174. struct direct *readdir(DIR * dirp)
  175. {
  176.   static struct direct dp;
  177.  
  178.   if (dirp -> dd_cp == NULL)
  179.     return NULL;
  180.  
  181.   dp.d_namlen = dp.d_reclen =
  182.     strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));
  183.  
  184.   dp.d_ino = 0;
  185.  
  186.   dp.d_size = dirp -> dd_cp -> _d_size;
  187.   dp.d_mode = dirp -> dd_cp -> _d_mode;
  188.   dp.d_time = dirp -> dd_cp -> _d_time;
  189.   dp.d_date = dirp -> dd_cp -> _d_date;
  190.  
  191.   dirp -> dd_cp = dirp -> dd_cp -> _d_next;
  192.   dirp -> dd_loc++;
  193.  
  194.   return &dp;
  195. }
  196.  
  197.  
  198. void seekdir(DIR * dirp, long off)
  199. {
  200.   long i = off;
  201.   struct _dircontents *dp;
  202.  
  203.   if (off >= 0)
  204.   {
  205.     for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
  206.  
  207.     dirp -> dd_loc = off - (i + 1);
  208.     dirp -> dd_cp = dp;
  209.   }
  210. }
  211.  
  212.  
  213. long telldir(DIR * dirp)
  214. {
  215.   return dirp -> dd_loc;
  216. }
  217.  
  218.  
  219. static void free_dircontents(struct _dircontents * dp)
  220. {
  221.   struct _dircontents *odp;
  222.  
  223.   while (dp)
  224.   {
  225.     if (dp -> _d_entry)
  226.       free(dp -> _d_entry);
  227.  
  228.     dp = (odp = dp) -> _d_next;
  229.     free(odp);
  230.   }
  231. }
  232.  
  233.  
  234. static char *getdirent(char *dir)
  235. {
  236.   int done;
  237.   static int lower;
  238.  
  239.   if (dir != NULL)
  240.   {                                    /* get first entry */
  241.     hdir = HDIR_CREATE;
  242.     count = 1;
  243.     done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count);
  244.     lower = IsFileSystemFAT(dir);
  245.   }
  246.   else                                 /* get next entry */
  247.     done = DosFindNext(hdir, &find, sizeof(find), &count);
  248.  
  249.   if (done == 0)
  250.   {
  251.     if ( lower )
  252.       StringLower(find.achName);
  253.     return find.achName;
  254.   }
  255.   else
  256.   {
  257.     DosFindClose(hdir);
  258.     return NULL;
  259.   }
  260. }
  261.  
  262.  
  263. /* FAT / HPFS detection */
  264.  
  265. int IsFileSystemFAT(char *dir)
  266. {
  267.   static USHORT nLastDrive = -1, nResult;
  268.   ULONG lMap;
  269.   BYTE bData[64], bName[3];
  270. #ifdef __32BIT__
  271.   ULONG nDrive, cbData;
  272.   PFSQBUFFER2 pData = (PFSQBUFFER2) bData;
  273. #else
  274.   USHORT nDrive, cbData;
  275.   PFSQBUFFER pData = (PFSQBUFFER) bData;
  276. #endif
  277.  
  278.   if ( _osmode == DOS_MODE )
  279.     return TRUE;
  280.   else
  281.   {
  282.     /* We separate FAT and HPFS+other file systems here.
  283.        at the moment I consider other systems to be similar to HPFS,
  284.        i.e. support long file names and beeing case sensitive */
  285.  
  286.     if ( isalpha(dir[0]) && (dir[1] == ':') )
  287.       nDrive = to_up(dir[0]) - '@';
  288.     else
  289.       DosQueryCurrentDisk(&nDrive, &lMap);
  290.  
  291.     if ( nDrive == nLastDrive )
  292.       return nResult;
  293.  
  294.     bName[0] = (char) (nDrive + '@');
  295.     bName[1] = ':';
  296.     bName[2] = 0;
  297.  
  298.     nLastDrive = nDrive;
  299.     cbData = sizeof(bData);
  300.  
  301.     if ( !DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData) )
  302.       nResult = !strcmp(pData -> szFSDName + pData -> cbName, "FAT");
  303.     else
  304.       nResult = FALSE;
  305.  
  306.     /* End of this ugly code */
  307.     return nResult;
  308.   }
  309. }
  310.  
  311.  
  312. /* access mode bits and time stamp */
  313.  
  314. int GetFileMode(char *name)
  315. {
  316. #ifdef __32BIT__
  317.   FILESTATUS3 fs;
  318.   return DosQueryPathInfo(name, 1, &fs, sizeof(fs)) ? -1 : fs.attrFile;
  319. #else
  320.   USHORT mode;
  321.   return DosQFileMode(name, &mode, 0L) ? -1 : mode;
  322. #endif
  323. }
  324.  
  325. long GetFileTime(char *name)
  326. {
  327. #ifdef __32BIT__
  328.   FILESTATUS3 fs;
  329. #else
  330.   FILESTATUS fs;
  331. #endif
  332.   USHORT nDate, nTime;
  333.  
  334.   if ( DosQueryPathInfo(name, 1, (PBYTE) &fs, sizeof(fs)) )
  335.     return -1;
  336.  
  337.   nDate = * (USHORT *) &fs.fdateLastWrite;
  338.   nTime = * (USHORT *) &fs.ftimeLastWrite;
  339.  
  340.   return ((ULONG) nDate) << 16 | nTime;
  341. }
  342.  
  343. void SetFileTime(char *path, long stamp)
  344. {
  345.   FILESTATUS fs;
  346.   USHORT fd, ft;
  347.   USHORT nLength;
  348.   char szName[CCHMAXPATH];
  349.  
  350.   if ( DosQueryPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )
  351.     return;
  352.  
  353.   fd = (USHORT) (stamp >> 16);
  354.   ft = (USHORT) stamp;
  355.   fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;
  356.   fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;
  357.  
  358.   DosSetPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
  359. }
  360.  
  361.  
  362. /* FAT / HPFS name conversion stuff */
  363.  
  364. int IsFileNameValid(char *name)
  365. {
  366.   HFILE hf;
  367. #ifdef __32BIT__
  368.   ULONG uAction;
  369. #else
  370.   USHORT uAction;
  371. #endif
  372.  
  373.   switch( DosOpen(name, &hf, &uAction, 0, 0, FILE_OPEN,
  374.                   OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0) )
  375.   {
  376.   case ERROR_INVALID_NAME:
  377.   case ERROR_FILENAME_EXCED_RANGE:
  378.     return FALSE;
  379.   case NO_ERROR:
  380.     DosClose(hf);
  381.   default:
  382.     return TRUE;
  383.   }
  384. }
  385.  
  386.  
  387. void ChangeNameForFAT(char *name)
  388. {